﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.StorageClient.Protocol;
using AzureGames.Model;
using System.Collections.Specialized;

using AzureGames.Data.Implementation.ServiceEntities;

namespace AzureGames.Data.Implementation
{
    public class GameDefinitionRepository : AzureTableRepository<GameDefinitionEntity>, IGameDefinitionRepository
    {
        const string PARTITIONKEY = "GameDefinition";
        internal GameResourceRepository GameResourceRepository { get; set; }
        internal GamePropertyRepository GamePropertyRepository { get; set; }

        public GameDefinitionRepository() : base("GameDefinition") {
            GameResourceRepository = new GameResourceRepository();
            GamePropertyRepository = new GamePropertyRepository();

            AutoMapper.Mapper.CreateMap<Model.GameDefinition, ServiceEntities.GameDefinitionEntity>()
                .ForMember(m => m.PartitionKey, s => s.UseValue("GameDefinition"))
                .ForMember(m => m.RowKey, s => s.MapFrom(g => g.ID));

            AutoMapper.Mapper.CreateMap<ServiceEntities.GameDefinitionEntity, Model.GameDefinition>();                
        }

        public List<GameDefinition> GetGameDefinitions()
        {
           var entities = Get(PARTITIONKEY);

           foreach (var entity in entities)
           {
               entity.CSSFiles = GameResourceRepository.GetGameResources(entity.ID, "CSS");
               entity.Media = GameResourceRepository.GetGameResources(entity.ID, "Media");
               entity.JavascriptFiles = GameResourceRepository.GetGameResources(entity.ID, "JavaScript");
               entity.StartingProperties = GamePropertyRepository.GetGameProperties(entity.ID);
           }


            // TODO: failing to perform a cast var l = entities.Cast<GameDefinition>().ToList();

           var defs = new List<GameDefinition>();
           foreach (var entity in entities)
           {
               defs.Add(GameDefinitionEntity.ToModel(entity));
           }

           return defs;
        }       

        public GameDefinition GetGameDefinition(int ID)
        {
            var entity = Get(PARTITIONKEY, ID.ToString());
            if (entity != null)
            {
                entity.CSSFiles = GameResourceRepository.GetGameResources(entity.ID, "CSS");
                entity.Media = GameResourceRepository.GetGameResources(entity.ID, "Media");
                entity.JavascriptFiles = GameResourceRepository.GetGameResources(entity.ID, "JavaScript");
                entity.StartingProperties = GamePropertyRepository.GetGameProperties(entity.ID);
            }
            return entity;
        }

        public AzureResult AddGameDefinition(GameDefinition gameDefinition)
        {
            Add(gameDefinition);

            ProcessGameResources(gameDefinition.ID, gameDefinition.CSSFiles, "CSS");
            ProcessGameResources(gameDefinition.ID, gameDefinition.Media, "Media");
            ProcessGameResources(gameDefinition.ID, gameDefinition.JavascriptFiles, "JavaScript");
            ProcessGameProperties(gameDefinition.ID, gameDefinition.StartingProperties);

            return new AzureResult { Code = 0 };
        }



        public AzureResult UpdateGameDefinition(GameDefinition gameDefinition)
        {
            throw new NotImplementedException();
        }

        private void ProcessGameResources(int gameID, List<Guid> resources, string resourceType)
        {
            // order is important so use for loop
            for (int i = 0; i < resources.Count; i++)
            {
                var resource = GameResourceRepository.GetGameResource(resources[i]);

                // should always be null unless this is from a refresh
                if (resource == null)
                    GameResourceRepository.AddGameResource(new GameResourceEntity
                    {
                        PartitionKey = "GameResource",
                        RowKey = resources[i].ToString(),
                        GameID = gameID,
                        CreatedDate = DateTime.Now,
                        ID = resources[i],
                        LastUpdatedDate = DateTime.Now,
                        ResourceOrder = i,
                        ResourceType = resourceType
                    });
                else
                {
                    // if the order has changed
                    if (resource.ResourceOrder != i)
                    {
                        resource.ResourceOrder = i;
                        GameResourceRepository.UpdateGameDefinition(resource);
                    }
                }
            }
        }

        private void ProcessGameProperties(int gameID, List<string> properties)
        {
            // order is important so use for loop
            for (int i = 0; i < properties.Count; i++)
            {
                var property = GamePropertyRepository.GetGameProperty(gameID, i);

                // should always be null unless this is from a refresh
                if (property == null)
                    GamePropertyRepository.AddGameProperty(new GamePropertyEntity
                        {
                            PartitionKey = "GameProperty",
                            RowKey = string.Format("{0}:{1}", gameID, i),
                            CreatedDate = DateTime.Now,
                            GameID = gameID,
                            LastUpdatedDate = DateTime.Now,
                            PropertyOrder = i,
                            PropertyValue = properties[i]
                        });
                else
                {
                    if (property.PropertyValue != properties[i])
                    {
                        property.PropertyValue = properties[i];
                        GamePropertyRepository.UpdateGameProperty(property);
                    }
                }
            }
        }

    }
}
